package com.ruoyi.system.service.impl;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.ruoyi.common.config.AppConfig;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.message.MessageIsRead;
import com.ruoyi.common.enums.session.ConversationType;
import com.ruoyi.common.enums.session.IsMutedType;
import com.ruoyi.common.enums.session.IsTopType;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.domain.Message;
import com.ruoyi.system.domain.UserSessionRelation;
import com.ruoyi.system.domain.vo.MessageVO;
import com.ruoyi.system.domain.vo.SessionVO;
import com.ruoyi.system.domain.vo.SysUserVO;
import com.ruoyi.system.service.IMessageService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.IUserSessionRelationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.SessionMapper;
import com.ruoyi.system.domain.Session;
import com.ruoyi.system.service.ISessionService;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.persistence.criteria.CriteriaBuilder;

/**
 * 会话Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-09-23
 */
@Service
@Slf4j
public class SessionServiceImpl implements ISessionService {

    @Autowired
    private SessionMapper sessionMapper;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IUserSessionRelationService userSessionRelationService;


    @Autowired
    private IMessageService messageService;


    /**
     * 查询会话
     * 
     * @param id 会话主键
     * @return 会话
     */
    @Override
    public Session selectSessionById(String id)
    {
        return sessionMapper.selectSessionById(id);
    }

    /**
     * 查询会话列表
     * 
     * @param session 会话
     * @return 会话
     */
    @Override
    public List<Session> selectSessionList(Session session)
    {
        return sessionMapper.selectSessionList(session);
    }

    /**
     * 新增会话
     * 
     * @param session 会话
     * @return 结果
     */
    @Override
    public int insertSession(Session session)
    {
        session.setCreateTime(DateUtils.getNowDate());
        return sessionMapper.insertSession(session);
    }

    /**
     * 修改会话
     * 
     * @param session 会话
     * @return 结果
     */
    @Override
    public int updateSession(Session session)
    {
        session.setUpdateTime(DateUtils.getNowDate());
        return sessionMapper.updateSession(session);
    }

    /**
     * 批量删除会话
     * 
     * @param ids 需要删除的会话主键
     * @return 结果
     */
    @Override
    public int deleteSessionByIds(String[] ids)
    {
        return sessionMapper.deleteSessionByIds(ids);
    }

    /**
     * 删除会话信息
     * 
     * @param id 会话主键
     * @return 结果
     */
    @Override
    public int deleteSessionById(String id)
    {
        return sessionMapper.deleteSessionById(id);
    }

    @Override
    public boolean createChatSession(SessionVO sessionVO) {

        if (ConversationType.SINGLE.getCode().equals(sessionVO.getConversationType())) {
            // 一对一聊天
            SessionVO queryVO = new SessionVO();
            queryVO.setConversationType(sessionVO.getConversationType());
            queryVO.setUserId(sessionVO.getUserId());
            queryVO.setTargetId(sessionVO.getFriendInfo().getUserId());
            SessionVO result = this.sessionMapper.selUserFriendSession(queryVO);

            if(result != null){
                // 已经存在
                log.info("SessionServiceImpl.createChatSession 用户id:{} 和朋友id:{} 已存在会话:{}",
                        sessionVO.getUserId(),sessionVO.getFriendInfo().getUserId(),result.getId());
            }else {
                // 不存在  需要创建一个session
                SessionVO vo = new SessionVO();
                vo.setId(IdUtils.simpleUUID());
                vo.setConversationType(sessionVO.getConversationType());
                vo.setUserId(sessionVO.getUserId());
                vo.setTargetId(sessionVO.getFriendInfo().getUserId());
                // 对于一对一聊天，sessionName和avatar暂时不设置，根据userId和targetId设置
//                vo.setSessionName();
//                vo.setAvatar();

                vo.setParticipantIds(sessionVO.getUserId()+","+sessionVO.getFriendInfo().getUserId());

                setVOInfo(vo);

                this.sessionMapper.insertSession(vo);
                log.info("SessionServiceImpl.createChatSession 创建会话成功{}", vo);

                // 新增会话关联记录  优化：写一个批量插入的方法

                UserSessionRelation curUser = new UserSessionRelation();
                curUser.setId(IdUtils.simpleUUID());
                curUser.setUserId(sessionVO.getUserId());
                curUser.setSessionId(vo.getId());
                curUser.setIsMuted(IsMutedType.NO.getCode());
                curUser.setIsTop(IsTopType.NO.getCode());
                curUser.setUnreadCount(0);

                userSessionRelationService.insertUserSessionRelation(curUser);


                UserSessionRelation targetUser = new UserSessionRelation();
                targetUser.setId(IdUtils.simpleUUID());
                targetUser.setUserId(sessionVO.getFriendInfo().getUserId());
                targetUser.setSessionId(vo.getId());
                targetUser.setIsMuted(IsMutedType.NO.getCode());
                targetUser.setIsTop(IsTopType.NO.getCode());
                targetUser.setUnreadCount(0);

                userSessionRelationService.insertUserSessionRelation(targetUser);

            }


        }else if(ConversationType.GROUP.getCode().equals(sessionVO.getConversationType())){
            // 群聊


        }

        return true;
    }

    /**
     * TODO 优化成：用户-会话的未读消息数，在容器启动的时候，加载到redis中，之后的数据扭转，都是在redis中操作
     * @param sessionVO
     * @return
     */
    @Override
    @Retryable(value = Exception.class, maxAttempts = 4, backoff = @Backoff(delay = 1000, multiplier = 1.5))
    public List<SessionVO> querySessionList(SessionVO sessionVO)throws Exception {
        List<SessionVO> result = this.sessionMapper.querySessionList(sessionVO);
        if(SessionVO.OpsFunc.getUnReadMsgList.getText().equals(sessionVO.getOpsFunc())){
            // 这段逻辑是 给 getUnReadMsgList 接口调用设置 只需要获取当前用户的会话
            return result;
        }

        List<String> sessionIds = result.stream().map(vo -> {
            return vo.getId();
        }).collect(Collectors.toList());

        MessageVO queryVO = new MessageVO();
        queryVO.setSessionIds(sessionIds);
        List<MessageVO> allMessage = messageService.getAllMsgList(queryVO);

        HashMap<String, MessageVO> allMessageMap = new HashMap<>();
        for (MessageVO message : allMessage) {
            allMessageMap.put(message.getId(), message);
        }

        HashMap<String,Boolean> sessionMap = new HashMap<>();

        // 设置会话头像和名称
        if(!CollectionUtils.isEmpty(result)){
            for (SessionVO vo : result) {

                // 设置未读消息数
                String sessionId = vo.getId();
                // messageUnReadList 包含了 离线未读消息
                List<String> messageUnReadList = allMessage.stream()
                        .filter(item -> item.getConversationId().equals(sessionId) && MessageIsRead.NO.getCode().equals(item.getIsRead()) &&
                                item.getReceiverId() != null && item.getReceiverId().equals(sessionVO.getUserId()))
                        .map(item -> {
                            return item.getId();
                        }).collect(Collectors.toList());
                log.info("SessionServiceImpl.querySessionList messageUnReadList:{}", messageUnReadList);

//                String key = StringUtils.handleString(CacheConstants.USER_UNREAD_LIST, sessionId, String.valueOf(SecurityUtils.getUserId()));
//                log.info("SessionServiceImpl.querySessionList key:{}", key);
//                redisCache.setCacheObject(key, messageUnReadList);

                vo.setUnreadCount(messageUnReadList.size());

                // 设置当前会话的最后一条消息
                if(StringUtils.isNotEmpty(vo.getLastMsgId()) && allMessageMap.containsKey(vo.getLastMsgId())){
                    MessageVO message = allMessageMap.get(vo.getLastMsgId());
                    vo.setLastMessage(message);
                }
                sessionMap.put(vo.getId(),false);  // 设置初始值为 false

                String participantIds = vo.getParticipantIds();
                if(null != participantIds){
                    if(ConversationType.SINGLE.getCode().equals(vo.getConversationType())){
                        String[] ids = participantIds.split(",");
                        if(ids.length > 2){
                            log.error("SessionServiceImpl.querySessionList 数据错误 一对一聊天类型下，参与者id数量大于2:{}",ids);
                            break;
                        }

                        for (String id : ids) {
                            long targetId = Long.parseLong(id);
                            if(targetId == sessionVO.getUserId()){
                                continue;
                            }
                            vo.setTargetId(targetId);
                            SysUser friendVO = sysUserService.selectUserById(targetId);
                            if(null != friendVO){
                                log.info("SessionServiceImpl.querySessionList 获取到会话的参与者信息:{}",friendVO);
                                vo.setAvatar(friendVO.getAvatar());
                                vo.setSessionName(friendVO.getNickName());
                            }
                        }
                    }else if(ConversationType.GROUP.getCode().equals(vo.getConversationType())){
                        // 群聊的头像和名称 会在会话记录中设置，所以无需处理
                    }
                }
            }
        }
//        String key = CacheConstants.USER_CUR_SESSION + SecurityUtils.getUserId();

//        if(StringUtils.isNotEmpty(queryVO.getConversationId())){
//            redisCache.setCacheMapValue(key,queryVO.getConversationId(),true);
//        }else {
            redisCache.setCacheMap(CacheConstants.USER_CUR_SESSION + SecurityUtils.getUserId(),sessionMap);
//        }

        // TODO  枚举处理
        handleSessionListEnum(result);
        return result;
    }

    @Override
    public void setSessionSelectedStatus(SessionVO sessionVO) {
        String curKey = CacheConstants.USER_CUR_SESSION + SecurityUtils.getUserId();
        Map<String, Boolean> cacheMap = redisCache.getCacheMap(curKey);
        if(ObjectUtils.isEmpty(cacheMap)){
            return;
        }
        if(StringUtils.isNotEmpty(sessionVO.getPreId())){
            cacheMap.put(sessionVO.getPreId(),false);
        }
        if(StringUtils.isNotEmpty(sessionVO.getCurId())){
            cacheMap.put(sessionVO.getCurId(),true);
        }

        redisCache.setCacheMap(curKey,cacheMap);
    }

    /**
     * 调用时机  待确定
     * @param sessionVO
     */
    @Override
    public void updateSessionVOInfo(SessionVO sessionVO) {
        if(ObjectUtils.isEmpty(sessionVO)){
            log.info("SessionServiceImpl.updateUnreadCount sessionVO is null");
            return;
        }

        if(StringUtils.isEmpty(sessionVO.getId()) || sessionVO.getUserId() == null){
            log.info("SessionServiceImpl.updateUnreadCount 参数格式不正确，sessionID:{},userId：{}",sessionVO.getId(),sessionVO.getUserId());
            return;
        }

        // 更改会话列表中最近一条消息记录  TODO 当没有sessionVO.getMessageId()==null的时候，最后一条消息从数据库中获取
        MessageVO queryVO = new MessageVO();
        queryVO.setSessionIds(Collections.singletonList(sessionVO.getId()));
        List<MessageVO> allMsgList = messageService.getAllMsgList(queryVO);

        if(!CollectionUtils.isEmpty(allMsgList)){

            List<MessageVO> messageVOS = allMsgList.stream().sorted(Comparator.comparing(MessageVO::getSendTime).reversed()).collect(Collectors.toList());
            // allMsgList 变成map
            Map<String, MessageVO> messageMap = messageVOS.stream().collect(Collectors.toMap(MessageVO::getId, messageVO -> messageVO));
            MessageVO messageVO = null;
            if (StringUtils.isNotEmpty(sessionVO.getMessageId())) {
                messageVO = messageMap.get(sessionVO.getMessageId());
            }else {
                messageVO = messageVOS.get(0);
            }

            String sessionId = sessionVO.getId();
            Session session = selectSessionById(sessionId);
            if(!ObjectUtils.isEmpty(session) && !ObjectUtils.isEmpty(messageVO)){
                session.setLastMsgId(messageVO.getId());
                session.setLastMessageTime(messageVO.getSendTime());

                updateSession(session);
            }
        }
    }

    private void handleSessionListEnum(List<SessionVO> result) {
        if(CollectionUtils.isEmpty( result)){
            return;
        }
        for (SessionVO vo : result) {
            handleSessionEnum(vo);
        }
    }

    private void handleSessionEnum(SessionVO vo) {
        if(null != vo){

            if (vo.getIsTop() != null) {

                if(IsTopType.YES.getCode().equals(vo.getIsTop())){
                    vo.setIsTopText(IsTopType.YES.getInfo());
                }else if(IsTopType.NO.getCode().equals(vo.getIsTop())){
                    vo.setIsTopText(IsTopType.NO.getInfo());
                }
            }

            if (vo.getIsMuted() != null) {

                if(IsMutedType.YES.getCode().equals(vo.getIsMuted())){
                    vo.setIsMutedText(IsMutedType.YES.getInfo());
                }else if(IsMutedType.NO.getCode().equals(vo.getIsMuted())){
                    vo.setIsMutedText(IsMutedType.NO.getInfo());
                }
            }

            if (vo.getConversationType() != null) {

                if(ConversationType.SINGLE.getCode().equals(vo.getConversationType())){
                    vo.setConversationTypeText(ConversationType.SINGLE.getInfo());
                }else if(ConversationType.GROUP.getCode().equals(vo.getConversationType())){
                    vo.setConversationTypeText(ConversationType.GROUP.getInfo());
                }
            }


            if(vo.getParticipantIds() != null){
                SysUserVO sysUserVO = new SysUserVO();
                List<SysUserVO> sysUsers = sysUserService.queryUserList(sysUserVO);

                HashMap<Long, SysUser> map = new HashMap<>();
                for (SysUser sysUser : sysUsers) {
                    map.put(sysUser.getUserId(),sysUser);
                }

                HashMap<Long, String> participantMap = new HashMap<>();
                for (String id : vo.getParticipantIds().split(",")){
                    participantMap.put(Long.parseLong(id),map.get(Long.parseLong(id)).getNickName());
                }

                vo.setParticipantMap(participantMap);
            }

        }
    }
}
